/*
 *  Autores: Claudio Djohnnatha, David Guilherme, Jailson Lima e Jordan Lira.
 *
 *  Projeto da disciplina Linguagem de Programação 2.
 *
 *  Arquivo: EditorApplication.java
 *
 *  Data: 27/08/2013
 *
 */

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.net.Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

public class ClientApplication
{

    public static void main(String[] args)
    {
        Client client = new Client();
    }
} // fim de ClientApplication.

class Client
{

    //Login
    private String[] loginInfo;
    
    // Editor.
    private EditorOnline editor;

    // Mensagem do servidor.
    private String fromServer;

    // Variável booleana utilizada para mandar um pedido de conecção para o servidor uma única vez.
    private boolean initialized = false;

    // Conecções com o servidor.
    private Socket s;
    private DataInputStream in;
    private DataOutputStream out;

    private boolean ping_value = false;

    private boolean ping_block = false;

    public Client()
    {
        // Cria o editor online.
        
        editor = new EditorOnline();

        try
        {
            // Tenta iniciar uma conecção com o servidor.
            boolean initConnecting = false;
            while (!initConnecting)
            {
                try
                {
                    s = connect();
                    in = new DataInputStream(s.getInputStream());
                    out = new DataOutputStream(s.getOutputStream());
                    editor.connected(); // modifica o status da janela para conectado, e permite interação do usuário.
                    initConnecting = true;
                } catch (IOException e)
                {
                    // System.out.println( "TENTANDO SE CONECTAR!" );
                }
            }

            // Passa a referência do stream de saída para o editor.
            editor.setOutput(out);

            //Ping ping = new Ping( this );
            //ping.start();
            startPing();

            while (true)
            {
                try
                {
                    if (!initialized)
                    {
                        out.writeUTF("CONNECTING");
                        initialized = true;
                    }

                    fromServer = in.readUTF(); // Ler o que o ProtocolServer escrveu.

                    if (fromServer.equals("DESCONNECTED"))
                    {
                        break;
                    }

                    if (fromServer.equals("PING"))
                    {
                        ping_value = true;
                    } else
                    {
                        editor.writeTextPane(fromServer);
                    }
                } catch (IOException e)
                {
                    reconnect();
                }

            } // fim do while.

            // Fecha os stream.
            in.close();
            out.close();
            s.close();
        } catch (IOException e)
        {
        }

    } // fim do método main.

    public String[] login()
    {
        JPanel panel = new JPanel(new BorderLayout(5, 5));

        JPanel label = new JPanel(new GridLayout(0, 1, 2, 2));
        label.add(new JLabel("Login", SwingConstants.RIGHT));
        label.add(new JLabel("Servidor:", SwingConstants.RIGHT));
        panel.add(label, BorderLayout.WEST);

        JPanel controls = new JPanel(new GridLayout(0, 1, 2, 2));
        JTextField username = new JTextField();
        controls.add(username);
        JTextField serverIp = new JTextField();
        controls.add(serverIp);
        panel.add(controls, BorderLayout.CENTER);

        JOptionPane.showMessageDialog(null, panel, "login", JOptionPane.QUESTION_MESSAGE);

        String[] loginInfo =
        {
            username.getText(), serverIp.getText()
        };
        return loginInfo;
    }
    public Socket connect() throws IOException
    {
        loginInfo = login();
        return new Socket(loginInfo[1], 4444); // 127.0.0.1 indica máquina local.
    }

    public DataOutputStream getOutput()
    {
        return out;
    }

    public DataInputStream getInput()
    {
        return in;
    }

    public void setPing(boolean p)
    {
        ping_value = p;
    }

    public boolean getPing()
    {
        return ping_value;
    }

    public void reconnect()
    {

        // System.out.println( "SERVIDOR CAIU!" );
        editor.desconnected();

        // Tenta iniciar uma conecção com o servidor.
        boolean initConnecting = false;
        while (!initConnecting)
        {
            try
            {
                s = connect();
                in = new DataInputStream(s.getInputStream());
                out = new DataOutputStream(s.getOutputStream());
                editor.connected(); // modifica o status da janela para conectado, e permite interação do usuário.
                initConnecting = true;
            } catch (IOException exception)
            {
                // System.out.println( "TENTANDO SE RECONECTAR!" );
            }
        }

        // Passa a referência do stream de saída para o editor.
        editor.setOutput(out);
        editor.updateState();

        startPing();
    }

    public void startPing()
    {
        Ping ping = new Ping(this);
        ping.start();
    }

}

class Ping extends Thread
{

    private Client client;
    private DataOutputStream output;
    private DataInputStream input;

    public Ping(Client c)
    {
        client = c;
        output = client.getOutput();
        input = client.getInput();
    }

    public void run()
    {
        while (true)
        {
            try
            {
                output.writeUTF("PING");
            } catch (IOException e)
            {
            }
            client.setPing(false);
            try
            {
                Thread.sleep(3000);
            } catch (InterruptedException e)
            {
            }
            if (client.getPing() == false)
            {
                try
                {
                    input.close();
                    output.close();
                    return;
                } catch (IOException e)
                {
                }
            }
        }
    }
}
